package com.ysten.basic.common.log.listener;

import java.io.Serializable;
import java.lang.reflect.Field;
import java.util.List;
import java.util.Map;

import org.apache.commons.collections.CollectionUtils;
import org.hibernate.ejb.event.EJB3PostDeleteEventListener;
import org.hibernate.event.spi.PostDeleteEvent;
import org.hibernate.persister.entity.EntityPersister;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.ysten.basic.common.log.config.PropertyLogConfiguration;
import com.ysten.basic.common.log.util.OperationType;
import com.ysten.basic.common.log.util.PropertyLogConstants;
import com.ysten.basic.common.log.util.PropertyLogUtils;

/**
 * <<记录表-删除 日志>>
 * 
 * @author 陆小凤
 * @version [1.0, 2015年9月14日]
 */
@SuppressWarnings({"serial"})
public class PostDeleteEventListener extends EJB3PostDeleteEventListener
{
    
    private static final Logger logger = LoggerFactory.getLogger(PostDeleteEventListener.class);
    
    @Override
    public void onPostDelete(PostDeleteEvent event)
    {
        Map<String, List<String>> configuration = PropertyLogConfiguration.INSTANCE.getConfiguration();
        
        String entityName = event.getEntity().getClass().getSimpleName();
        if (!configuration.containsKey(entityName))
        {
            return;
        }
        
        Map<String, Object> map = Maps.newHashMap();
        try
        {
            map = getContent(event, configuration.get(entityName));
            PropertyLogUtils.processNormal(map, event.getSession().connection(), OperationType.DELETE);
        }
        catch (Exception e)
        {
            logger.error("process postDelete error.", e);
        }
        
        super.onPostDelete(event);
    }
    
    private Map<String, Object> getContent(PostDeleteEvent event, List<String> propertyList)
        throws IllegalArgumentException, IllegalAccessException, InstantiationException, ClassNotFoundException
    {
        Map<String, Object> map = Maps.newHashMap();
        EntityPersister persister = event.getPersister();
        Object entity = event.getEntity();
        
        Serializable[] serializables = event.getPersister().getPropertySpaces();
        map.put(PropertyLogConstants.KEY_TABLENAME, serializables[0]);
        
        String identifierPropertyName = persister.getIdentifierPropertyName();
        Field[] declaredFields = entity.getClass().getDeclaredFields();
        
        String fieldName = null;
        for (int i = 0; i < declaredFields.length; i++)
        {
            fieldName = declaredFields[i].getName();
            if (fieldName.equals(identifierPropertyName))
            {
                List<Map<String, Object>> pkList = Lists.newArrayList();
                if (!persister.getPropertyType(fieldName).isEntityType())
                {
                    Map<String, Object> pkMap = Maps.newHashMap();
                    declaredFields[i].setAccessible(true);
                    pkMap.put(fieldName, declaredFields[i].get(entity));
                    pkList.add(pkMap);
                }
                else
                {
                    Class<?> obj = event.getId().getClass();
                    Field[] objFields = obj.getDeclaredFields();
                    for (int j = 0; j < objFields.length; j++)
                    {
                        if (objFields[j].getName().equals("serialVersionUID"))
                        {
                            continue;
                        }
                        objFields[j].setAccessible(true);
                        Map<String, Object> pkMap = Maps.newHashMap();
                        pkMap.put(objFields[j].getName(), objFields[j].get(event.getId()));
                        pkList.add(pkMap);
                    }
                }
                
                map.put(PropertyLogConstants.KEY_PKNAME, pkList);
            }
        }
        
        StringBuilder builder = new StringBuilder();
        
        for (int i = 0; i < event.getDeletedState().length; i++)
        {
            String propertyName = persister.getPropertyNames()[i];
            if (!CollectionUtils.isEmpty(propertyList) && !propertyList.contains(propertyName))
            {
                continue;
            }
            
            if (persister.getPropertyType(propertyName).isCollectionType()
                || persister.getPropertyType(propertyName).isEntityType())
            {
                continue;
            }
            
            if (!StringUtils.isEmpty(builder.toString()))
            {
                builder.append("$");
            }
            
            builder.append(propertyName).append("=").append(event.getDeletedState()[i]);
        }
        
        map.put(PropertyLogConstants.KEY_PREVIOUS_PROPERTY, builder.toString());
        
        return map;
    }
}
